#!/bin/python3
# -*- coding:utf-8 -*-
"""
    [模块名]
    By :陈狍子 e4ting@qq.com 2024-12-07 22:18:55
"""
import sys,os
from pdb import set_trace as strace
from traceback  import format_exc as dumpstack

from e4ting import util,log

from .cards        import Cards
from core.cache    import RoundCache

class GameRound(object):
    """ 游戏回合 """
    minimum = 0
    def __init__(self, btn=0, game=None, judge=None):
        # super(GameRound, self).__init__()
        self.players = []
        self.btn = btn
        self.game = game
        self.judge = judge
        self.is_stop_bet = False
        self.common = []
        self.uid = str(RoundCache.game)

    def init(self):
        """ 计算下注顺序 """
        self.indexs = [ pos % len(self.players) for pos in range(self.judge.sblind, self.judge.sblind + len(self.players) )]
        log.info("清理玩家缓存")
        for player in self.players:
            player.clear_cache()

    def set_players(self, players):
        self.players = players

    def clear_all_raise(self):
        for player in self.players:
            player.clear_cache("raise")

    def save_player_bet(self):
        log.info(f"保存{self} 所有玩家下注信息")
        for player in self.players:
            player.incr_bet()

    def player_do_bet(self, player, amount=10, force=False):
        """ 玩家需要补齐到 amount """

        # 先读取已下注
        bet = player.get("bet")

        assert bet <= amount, "已下注({})大于本轮底注({})".format(bet, amount)

        minimum = amount - bet
        # 最少还需要下注额度
        ret = player.do_bet(minimum, Round=self, force=force)

        player.clear_cache("raise")
        player.set("bet", ret)
        if player.get("bet") > self.minimum:
            # 如果下注额度超过本轮底注，说明玩家 raise 了
            self.clear_all_raise()
            player.set("raise", "true")
            log.info("{player} raise ".format(player=player))
        self.minimum = max(player.get("bet"), self.minimum)

    def is_someone_raise(self):
        log.info(self.players)
        return any([player.get("raise") for player in self.players])

    def turn_bet(self):
        for pos in self.indexs:
            player = self.players[pos]
            self.player_do_bet(player, self.minimum)

    def raise_bet(self):
        for pos in self.indexs:
            player = self.players[pos]
            if player.get("raise") == "true":
                # 转了一圈回来，raise标记还在自己身上，不可再raise了
                player.clear_cache("raise")
                break
            player = self.players[pos]
            self.player_do_bet(player, self.minimum)
            if not self.is_someone_raise():
                break

    def send_cards(self):
        cards = self.get_cards()
        if not cards:
            return True
        log.info(f"发送公牌 {cards}")
        return True

    def webdump(self):
        return dict(
            uid=self.uid,
            name=self.__doc__.strip(),
            cards=self.get_cards(),
            )

    def run(self):
        # 最少下注一圈
        log.info(self)
        self.send_cards()
        self.turn_bet()
        while self.is_someone_raise():
            self.raise_bet()
            # 没人加注就下一轮
        self.save_player_bet()


    def __repr__(self):
        return self.__doc__.strip()

class DealCardsRound(GameRound):
    """ 发牌 """

    def get_cards(self):
        return []

    def run(self):
        # 发一副牌
        self.cards = Cards(member=len(self.players), type="short") # , type="flush"
        self.common = self.cards.common
        for pos in self.indexs:
            player = self.players[pos]
            cards  = self.cards.players[pos]
            player.do_deal_cards(cards)

        self.judge.set_common(self.common)

        log.info(self)

    def __repr__(self):
        if self.common:
            return "{doc} 公牌 {self.common}".format(doc=self.__doc__.strip(), self=self)
        return self.__doc__.strip()

class PreFlopRound(GameRound):
    """盲注圈"""
    minimum = 0

    def init(self):
        """ 计算下注顺序 """
        self.minimum = self.judge.minimum * 2
        log.info("枪口位 {self.judge.utg}: {play}".format(self=self, play=self.players[self.judge.utg]))
        # strace()
        self.indexs = [ pos % len(self.players) for pos in range(self.judge.utg, self.judge.utg + len(self.players) )]
        self.is_big_raise = False

    def small_blind_bet(self):
        player = self.players[self.judge.sblind]
        # strace()
        self.player_do_bet(player, self.judge.minimum, force=True)
        self.clear_all_raise()
        player.set("raise", "true")
        log.info("小盲 {player} 已下注".format(player=player, self=self) )

    def big_blind_bet(self):
        player = self.players[self.judge.bblind]
        # strace()
        self.player_do_bet(player, self.judge.minimum * 2, force=True)
        # player.do_bet(self.judge.minimum * 2)
        player.set("blind_raise", "true") # 大盲有一次额外的raise机会
        self.clear_all_raise()
        player.set("raise", "true")
        log.info("大盲 {player} 已下注".format(player=player) )

    def prebet(self):
        """ 发牌前的下注行为 """
        # 发牌前小盲下注
        self.small_blind_bet()
        # 发牌前大盲下注
        self.big_blind_bet()

    def turn_bet(self):
        # 最少下注一圈
        # strace()
        for pos in self.indexs:
            player = self.players[pos]

            # 大盲有一次额外的raise的机会
            if player.get("blind_raise") == "true":
                player.set("blind_raise", "false")
                # strace()
                self.player_do_bet(player, self.minimum)
                continue
            self.player_do_bet(player, self.minimum)

    def get_cards(self):
        return []
    # def get_cards(self):
    #     return [
    #         self.judge.common[0].webdump(hiden=True),
    #         self.judge.common[1].webdump(hiden=True),
    #         self.judge.common[2].webdump(hiden=True),
    #         self.judge.common[3].webdump(hiden=True),
    #         self.judge.common[4].webdump(hiden=True),
    #      ]

    # def send_cards(self):
    #     data = self.get_cards()
    #     self.judge.send_commons(data)

    def run(self):
        self.prebet()
        super().run()

class FlopRound(GameRound):
    """ 押注圈 """
    minimum = 0

    def get_cards(self):
        return [
            self.judge.common[0].webdump(),
            self.judge.common[1].webdump(),
            self.judge.common[2].webdump(),
            self.judge.common[3].webdump(hiden=True),
            self.judge.common[4].webdump(hiden=True),
         ]

    def send_cards(self):
        data = self.get_cards()
        self.judge.send_commons(data)

class TurnRound(GameRound):
    """ 转牌圈 """
    minimum = 0

    def get_cards(self):
        return [
            self.judge.common[0].webdump(),
            self.judge.common[1].webdump(),
            self.judge.common[2].webdump(),
            self.judge.common[3].webdump(),
            self.judge.common[4].webdump(hiden=True),
         ]

    def send_cards(self):
        data = self.get_cards()
        self.judge.send_commons(data)

class RiverRound(GameRound):
    """ 河牌圈 """
    minimum = 0

    def get_cards(self):
        return [
            self.judge.common[0].webdump(),
            self.judge.common[1].webdump(),
            self.judge.common[2].webdump(),
            self.judge.common[3].webdump(),
            self.judge.common[4].webdump(),
         ]

    def send_cards(self):
        data = self.get_cards()
        log.info(f"发送公牌 {data}")
        self.judge.send_commons(data)
